package com.fet.sc.util;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import fet.org.apache.poi.ss.usermodel.Cell;
import fet.org.apache.poi.ss.usermodel.Row;
import fet.org.apache.poi.xssf.usermodel.XSSFCell;
import fet.org.apache.poi.xssf.usermodel.XSSFSheet;
import fet.org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * <ul>
 * 過濾檔案問題字串
 * </ul>
 * <li>因應 BAU CODE SCAN  Input-Based Attacks的issue ,Chen, Gary 
 * <li>Input-Based Attacks(如FileInputStream)，建議還是需在資料輸入或輸出之前，先使用一個filter function進行驗證，確保輸入或輸出的資料都是經過驗證
 * <li>使用正規表示過濾字串內容
 * </ul>
 * @author jeff
 * 
 */

public class KeywordsFilter {

	private Log logger = LogFactory.getLog(KeywordsFilter.class);

	private static Properties props = null;

	// 問題字串設定檔
	private static final String SC_FILE_NAME = "keywordsFilter.properties";

	
	/**
	 * 
	 * @param key 設定檔名稱
	 * @return 取得設定檔
	 */
	public String getProperty(String key) {
		if (props == null) {
			try {
				props = new Properties();
				props.load(KeywordsFilter.class.getClassLoader()
						.getResourceAsStream(SC_FILE_NAME));
			} catch (IOException e) {
				logger.error("Can't get property file: <" + SC_FILE_NAME + ">");
			}
		}
		return props.getProperty(key);
	}

	/**
	 * 驗證是否存在非法字串
	 * 
	 * @param fis
	 *            傳入欲檢核的資料 FileInputStream
	 * @return boolean true 存在
	 */
	public boolean checkcontent(FileInputStream fis)// 驗證是否存在非法字串
	{
		InputStreamReader isr = null;
//	try {
			isr = new InputStreamReader(fis);
//		} catch (UnsupportedEncodingException e) {
//			logger.error("Encoding error", e);
//		}

		BufferedReader br = new BufferedReader(isr);

		try {

			String tempstr = "";
			while ((tempstr = br.readLine()) != null) {
				//System.out.print(tempstr);
				if (checkcontent(tempstr))
					return true;
			}
			// BR RESET沒用的樣子 因為FIS已經用掉了?
			br.close();
			isr.close();
			fis.close();
		} catch (IOException e) {
			logger.error("close in error", e);
		}
		return false;
	}

	/**
	 * 使用poi驗證xls or excel檔案 是否存在非法字串
	 * 
	 * @param 傳入欲檢核的資料   FileInputStream 
	 * @param  傳入檔案名稱(檢核附檔類型) fileName         
	 * @return boolean default false (沒檢核出)
	 */
	public boolean checkXlscontent(FileInputStream fis,String fileName)//驗證xls是否存在非法字串 

	{
		HSSFWorkbook hwb = null;
		XSSFWorkbook xwb = null;		
		//logger.error("fileName.endsWith(xls) "+fileName.endsWith("xls"));
		if (fileName.endsWith("xls")) {
			try {
				hwb = new HSSFWorkbook(fis);
			
				HSSFSheet sheet = hwb.getSheetAt(0);

				HSSFCell cell;

				for (int i = 0; i < sheet.getPhysicalNumberOfRows(); i++) {
					// 第 0 Row 為 title,
					HSSFRow row = sheet.getRow(i); // 取得第 i Row
					if (row != null) {
						int j = 0;
						for (; j < sheet.getColumnWidth(i); j++) // 看資料需要的欄數
						{ 
							cell = row.getCell(0);
							if (cell != null)
							{			
								if (cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC
									&& cell.toString().endsWith(".0")) {	
									//logger.error("c "+checkcontent(cell.toString().split("\\.")[0]));
									return checkcontent(cell.toString().split("\\.")[0]);
								} else {	
									//logger.error("SS "+checkcontent(cell.toString()));
									return checkcontent(cell.toString());							
								}
							}
						}
					}
				}
			} catch (IOException e) {
				logger.error(e);
			}finally
			{
				if (null!= fis){
	                try{
	                    fis.close();
	                }catch (IOException e){
	                    logger.warn("",e);
	                }
	            }
	            fis = null;
	            hwb = null;
			}
	
		} else {
			try {
				xwb = new XSSFWorkbook(fis);
			
			XSSFSheet sheet = xwb.getSheetAt(0);
			Iterator<Row> rit = sheet.rowIterator();
			rit.next(); // 表頭
			for (; rit.hasNext();) {
				Row row = rit.next();

				Cell cell = row.getCell(0);
				if (cell != null) {
					if (cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC
							&& cell.toString().endsWith(".0")) {					  
						  return checkcontent(cell.toString().split("\\.")[0]);
					} else {						
						  return checkcontent(cell.toString());
						
					}

				}
			}
			} catch (IOException e) {
				logger.error(e);
			}finally
			{
				if (null!= fis){
	                try{
	                    fis.close();
	                }catch (IOException e){
	                    logger.warn("",e);
	                }
	            }
	            fis = null;
	            xwb = null;
			}

		}
		return false;
	}
	/**
	 * 使用poi驗證xls or excel檔案 是否存在非法字串
	 * 
	 * @param 傳入欲檢核的資料   InputStream 
	 * @param  傳入檔案名稱(檢核附檔類型) fileName         
	 * @return boolean default false (沒檢核出)
	 */
	public boolean checkXlscontent(InputStream fis,String fileName)//驗證xls是否存在非法字串 

	{
		
		HSSFWorkbook hwb = null;
		XSSFWorkbook xwb = null;		
		 logger.error("fileName.endsWith(xls) "+fileName.endsWith("xls"));
		if (fileName.endsWith("xls")) {
			try {
				hwb = new HSSFWorkbook(fis);
			
				HSSFSheet sheet = hwb.getSheetAt(0);

				HSSFCell cell;

				for (int i = 0; i < sheet.getPhysicalNumberOfRows(); i++) {
					// 第 0 Row 為 title,
					HSSFRow row = sheet.getRow(i); // 取得第 i Row
					if (row != null) {
						int j = 0;
						for (; j < sheet.getColumnWidth(i); j++) // 看資料需要的欄數
						{ 
							cell = row.getCell(0);
							if (cell != null)
							{			
								if (cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC
									&& cell.toString().endsWith(".0")) {	
									//logger.error("c "+checkcontent(cell.toString().split("\\.")[0]));
									return checkcontent(cell.toString().split("\\.")[0]);
								} else {	
									//logger.error("SS "+checkcontent(cell.toString()));
									return checkcontent(cell.toString());							
								}
							}
						}
					}
				}
			} catch (IOException e) {
				logger.error(e);
			}finally
			{
				if (null!= fis){
	                try{
	                    fis.close();
	                }catch (IOException e){
	                    logger.warn("",e);
	                }
	            }
	            fis = null;
	            hwb = null;
			}
	
		} else {
			try {
				xwb = new XSSFWorkbook(fis);
			
			XSSFSheet sheet = xwb.getSheetAt(0);
			Iterator<Row> rit = sheet.rowIterator();
			rit.next(); // 表頭
			for (; rit.hasNext();) {
				Row row = rit.next();

				Cell cell = row.getCell(0);
				if (cell != null) {
					if (cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC
							&& cell.toString().endsWith(".0")) {					  
						  return checkcontent(cell.toString().split("\\.")[0]);
					} else {						
						  return checkcontent(cell.toString());
						
					}

				}
			}
			} catch (IOException e) {
				logger.error(e);
			}finally
			{
				if (null!= fis){
	                try{
	                    fis.close();
	                }catch (IOException e){
	                    logger.warn("",e);
	                }
	            }
	            fis = null;
	            xwb = null;
			}

		}
		return false;
	}

	
	
	
	/**
	 * 使用matcher 驗證是否存在非法字串,pattern 來源為設定檔keywordsFilter.properties
	 * 
	 * @param 傳入欲檢核的資料 String content
	 *   
	 * @return boolean
	 */
	public boolean checkcontent(String content)// 驗證是否存在非法字串
	{

		KeywordsFilter kf = new KeywordsFilter();

		// 從keywordsFilter.properties 取得字串
		String exeTypes = kf.getProperty("all.keyword");
		  
		
		Pattern pattern = Pattern.compile(exeTypes);

		Matcher matcher = pattern.matcher(content.toLowerCase());
	
			if (matcher.find()) {
				return true;
			}
		

		return false;
	}

}
